package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FundAccountFlowTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.OtherIncomeSheetTypeEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.enums.UnitEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.pojo.vo.FormDataDeleteBatchVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.PaymentErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.otherincome.pojo.dto.OtherIncomeEditAttrUpdateDTO;
import com.xbongbong.pro.otherincome.pojo.dto.OtherIncomeSaveDTO;
import com.xbongbong.pro.otherincome.pojo.dto.OtherIncomeUpdateDTO;
import com.xbongbong.pro.otherincome.pojo.dto.batch.OtherIncomeUpdateBatchDTO;
import com.xbongbong.pro.service.toolbox.statistic.help.FormHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.SystemChartHelp;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.analytical.impl.OtherIncomeValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.domain.entity.FundAccountFlowEntity;
import com.xbongbong.saas.domain.entity.OtherIncomeEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.OtherIncomeEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasOtherIncomeHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.workflow.PayAndPaymentSheetHelp;
import com.xbongbong.saas.model.FundAccountFlowModel;
import com.xbongbong.saas.model.OtherIncomeModel;
import com.xbongbong.saas.service.FundAccountFlowService;
import com.xbongbong.saas.service.OtherIncomeService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static java.lang.String.format;

/**
 * @author zcp
 * @version v1.0
 * @since v1.0
 */
@Service("otherIncomeService")
public class OtherIncomeServiceImpl implements OtherIncomeService {
    private static final Logger LOG = LoggerFactory.getLogger(OtherIncomeServiceImpl.class);

    @Resource
    private SystemChartHelp systemChartHelp;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private OtherIncomeModel otherIncomeModel;
    @Resource
    private FundAccountFlowModel fundAccountFlowModel;
    @Resource
    private FundAccountFlowService fundAccountFlowService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private FormHelp formHelp;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private LogHelp logHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private OtherIncomeValidateAnalyticalServiceImpl otherIncomeAnalyticalService;
    @Resource
    private PayAndPaymentSheetHelp payAndPaymentSheetHelp;
    @Resource
    private SaasOtherIncomeHelp saasOtherIncomeHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private CommonHelp commonHelp;

    @Override
    public ListAppVO formatOtherIncomeAppList(FormDataListDTO formDataListDTO, List<PaasFormDataEntityExt> esEntities, Integer totalCount) throws XbbException {
        List<AppListPojo> appListPojos = new ArrayList<>();
        for (PaasFormDataEntityExt entityExt : esEntities) {
            JSONObject data = entityExt.getData();
            Long paymentSheetId = entityExt.getId();
            Long appId = entityExt.getAppId();
            Long menuId = entityExt.getMenuId();
            Long formId = entityExt.getFormId();
            List<FormTitlePoJo> titleList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.TITLE_LIST, new JSONArray()).toJavaList(FormTitlePoJo.class);
            List<SummaryDataPoJo> summaryList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.SUMMARY_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<SummaryDataPoJo> lablesList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.LABELS_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            JSONObject others = disposeOtherIncomeOthers(data);
            JSONObject superScript = new JSONObject();
            //app系统关联数据展示需要 others 和 superScript
            data.put(BusinessConstant.OTHERS, others);
            data.put(BusinessConstant.SUPER_SCRIPT, superScript);

            appListPojos.add(new AppListPojo(paymentSheetId, titleList, summaryList, superScript, lablesList, others, appId, menuId, formId));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(totalCount);
        return listAppVO;
    }

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        otherIncomeAnalyticalService.beforeSave(validateDataDTO);
    }

    @Override
    public FormDataAddVO add(OtherIncomeSaveDTO otherIncomeSaveDTO, PaasFormDataEntity paasFormDataEntity, PaasFormEntityExt paasFormEntityExt) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        JSONObject dataList = paasFormDataEntity.getData();
        Integer businessType = otherIncomeSaveDTO.getBusinessType();
        //删除不在mapping中的字段  兼容老数据
        fundHelp.removeNotInMapping(dataList);
        fundHelp.removeNotInMapping(otherIncomeSaveDTO.getDataList());
        if (Objects.equals(XbbRefTypeEnum.OTHER_INCOME.getCode(), businessType)) {
            saveOtherIncome(SheetTypeEnum.OTHER_INCOME, otherIncomeSaveDTO, paasFormDataEntity);
        } else if (Objects.equals(XbbRefTypeEnum.RED_OTHER_INCOME.getCode(), businessType)) {
            saveRedOtherIncome(SheetTypeEnum.RED_OTHER_INCOME, otherIncomeSaveDTO, paasFormDataEntity);
        }
        formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
        formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
        return formDataAddVO;
    }

    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject dataList = newPaasFormDataEntity.getData();
        Long addTime = newPaasFormDataEntity.getAddTime();
        String corpid = newPaasFormDataEntity.getCorpid();
        Long sheetId = newPaasFormDataEntity.getDataId();
        Double sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(dataList, OtherIncomeEnum.AMOUNT.getAttr(), 0D);
        Map<String, FieldAttrEntity> explainMap = saasFormSaveDTO.getExplainMap();
        Long accountId = FastJsonHelper.getLongOrDefaultFromFormData(dataList, OtherIncomeEnum.FUND_ACCOUNT.getAttr(), 0L);
        Long sheetTime = fundHelp.getSheetTime4FundFlow(dataList, OtherIncomeEnum.INCOME_TIME.getAttr(), explainMap, addTime);
        //账户余额变动（红冲类型的金额已经处理成负数）
        payAndPaymentSheetHelp.saveByPaymentSheetOrPaySheet(accountId, sheetAmount, corpid);
        //流水表日志记录
        FundAccountFlowEntity fundAccountFlowEntity = new FundAccountFlowEntity(corpid, addTime, newPaasFormDataEntity.getCreatorId(), FundAccountFlowTypeEnum.OTHER_INCOME.getCode(), sheetId, accountId, sheetTime, sheetAmount);
        fundAccountFlowModel.insert(fundAccountFlowEntity);
    }

    @Override
    public void batchEditAttr(OtherIncomeEditAttrUpdateDTO otherIncomeEditAttrUpdateDTO) throws XbbException {
        try {
            List<OtherIncomeUpdateDTO> otherIncomeUpdateList =new ArrayList<>();
            List<Long> dataIdList = otherIncomeEditAttrUpdateDTO.getDataIdList();
            String corpid = otherIncomeEditAttrUpdateDTO.getCorpid();
            List<String> fieldList = Arrays.asList("id", "flowStatus", OtherIncomeEnum.SHEET_NO.getAttr(), OtherIncomeEnum.getAttrConnectData(OtherIncomeEnum.SHEET_TYPE_OTHER));
            List<PaasFormDataEntityExt> entityList = formHelp.getFormListByIds4All(corpid, IndexTypeEnum.IDX_SAAS_OTHER_INCOME, dataIdList, fieldList);
            if (Objects.isNull(entityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(entityList.size());
            List<Long> idList = new ArrayList<>(entityList.size());
            for (PaasFormDataEntityExt entityExt : entityList) {
                Long id = entityExt.getId();
                JSONObject data = entityExt.getData();
                if (data == null) {
                    continue;
                }
                idList.add(id);
                updataItemList.add(entityExt.getSerialNo());
                OtherIncomeUpdateDTO updateDTO = new OtherIncomeUpdateDTO();
                updateDTO.setId(id);
                JSONObject updateData = ProSaveHelp.getBatchUpdateData(otherIncomeEditAttrUpdateDTO.getFieldEditedList());
                updateDTO.setData(updateData);
                otherIncomeUpdateList.add(updateDTO);
            }
            if (!otherIncomeUpdateList.isEmpty()) {
                OtherIncomeUpdateBatchDTO updateBatchDTO = new OtherIncomeUpdateBatchDTO();
                BeanUtil.copyProperties(otherIncomeEditAttrUpdateDTO, updateBatchDTO);
                updateBatchDTO.setUpdateList(otherIncomeUpdateList);
                updateAttrBatch(updateBatchDTO);

                String updataItem = StringUtils.join(updataItemList, "，");
                String userId = otherIncomeEditAttrUpdateDTO.getUserId();
                String loginUserName = otherIncomeEditAttrUpdateDTO.getLoginUserName();
                // 标签特殊处理
                Integer fieldType = otherIncomeEditAttrUpdateDTO.getFieldType();
                Boolean isFieldDependence = otherIncomeEditAttrUpdateDTO.getIsFieldDependence();
                logHelp.analysisLabel(corpid, fieldType, isFieldDependence,otherIncomeEditAttrUpdateDTO.getLogFieldEditedList());

                String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(otherIncomeEditAttrUpdateDTO.getLogFieldEditedList());
                if(idList.size() > 1 ){
                    String memo = format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.OTHER_INCOME.getName(), changedLogItemsStr, idList.size());
                    List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    InfoArrPojo infoArrPojo = new InfoArrPojo();
                    infoArrPojo.setTitle(XbbRefTypeEnum.OTHER_INCOME.getName());
                    infoArrPojo.setContent(updataItem);
                    infoArrPojoList.add(infoArrPojo);
                    mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.OTHER_FUND_MANAGEMENT, OperateTypeEnum.EDIT, "", "", memo, otherIncomeEditAttrUpdateDTO.getHttpHeader());
                } else if (Objects.equals(idList.size(), 1)){
                    String memo = format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.OTHER_INCOME.getName(), updataItem, changedLogItemsStr);
                    mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.OTHER_FUND_MANAGEMENT, OperateTypeEnum.EDIT, idList.get(0).toString(), updataItem, memo, otherIncomeEditAttrUpdateDTO.getHttpHeader());
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("OtherIncomeServiceImpl.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        // data 数据
        JSONObject dataJson = new JSONObject();
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        // 遍历数据
        for ( FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList ) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if ( Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType()) ) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else {
                if ( Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString()) ) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType()) ) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                }else {
                    if ( Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType()) ) {
                        formDataAddDTO.setSerialNo(cellValue.toString());
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                        importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                        importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                    } else {
                        dataJson.put(attr, cellValue);
                    }
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) {

    }

    @Override
    public FormDataDeleteBatchVO deleteBatch(FormDataDeleteBatchDTO formDataDeleteBatchDTO) throws XbbException {
        FormDataDeleteBatchVO formDataDeleteBatchVO = new FormDataDeleteBatchVO();
        otherIncomeModel.deleteBatch(formDataDeleteBatchDTO.getDataIdList(), formDataDeleteBatchDTO.getCorpid());
        formDataDeleteBatchVO.setDeleteIds(formDataDeleteBatchDTO.getDataIdList());
        return formDataDeleteBatchVO;
    }

    /**
     * 处理others字段
     *
     * @param data paymentSheet数据
     * @return com.alibaba.fastjson.JSONObject
     * @throws XbbException 异常
     * @author zcp
     * @since v1.0
     */
    private JSONObject disposeOtherIncomeOthers(JSONObject data) throws XbbException {
        JSONObject others = new JSONObject();
        //内部展示的是文字
        String status = commonHelp.formatFundStatusText(data, OtherIncomeEnum.SHEET_TYPE_OTHER.getAttr(),OtherIncomeSheetTypeEnum.UNKNOWN.getName());
        //文字转为code
        String type = OtherIncomeSheetTypeEnum.getByName(status).getCode();
        Double amount = FastJsonHelper.getDoubleOrDefaultFromFormData(data, OtherIncomeEnum.AMOUNT.getAttr(), BasicConstant.ZERO_DOUBLE);
        String amountStr = StringUtil.formatDouble(amount) + UnitEnum.MONEY.getName();
        others.put("amountStr", amountStr);
        others.put("status", status);
        //处理红冲状态
        boolean red = OtherIncomeSheetTypeEnum.isRed(type);
        int redStatus = red ? 1 : 0;
        others.put("isRed", redStatus);
        return others;
    }

    /**
     * 已收款保存
     * @param sheetTypeEnum
     * @param otherIncomeSaveDTO
     * @param paasFormDataEntity
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void saveOtherIncome(SheetTypeEnum sheetTypeEnum, OtherIncomeSaveDTO otherIncomeSaveDTO, PaasFormDataEntity paasFormDataEntity) throws XbbException{
        /*
         其他收入单已收款
         */
        Double sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(otherIncomeSaveDTO.getDataList(), OtherIncomeEnum.AMOUNT.getAttr(), 0D);
        //保存入库
        saveDb(sheetTypeEnum, otherIncomeSaveDTO, paasFormDataEntity, sheetAmount);
    }

    /**
     * 红冲已收款保存
     * @param sheetTypeEnum
     * @param otherIncomeSaveDTO
     * @param paasFormDataEntity
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void saveRedOtherIncome(SheetTypeEnum sheetTypeEnum, OtherIncomeSaveDTO otherIncomeSaveDTO, PaasFormDataEntity paasFormDataEntity) throws XbbException{
        /*
         红冲已收款：金额需校验是否可再红冲，且需处理成负数
         */
        JSONObject dataList = otherIncomeSaveDTO.getDataList();
        String corpid = otherIncomeSaveDTO.getCorpid();
        //先校验原单可红冲金额是否足够
        Long linkPreId = FastJsonHelper.getLongFromFormData(dataList, OtherIncomeEnum.ORIGIN_ID.getAttr());
        //关联原始收入单
        OtherIncomeEntity originEntity = otherIncomeModel.getByKey(linkPreId, corpid);
        if (Objects.isNull(originEntity)) {
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208045, PaymentErrorCodeEnum.API_ERROR_208045.getMsg(), OtherIncomeEnum.ORIGIN_ID.getAttrName());
        }
        JSONObject originData = JsonHelperUtil.getJSONObject(originEntity.getData());
        double originAmout = originData.getDoubleValue(OtherIncomeEnum.AMOUNT.getAttr());
        //原单已红冲金额
        double redAmount = saasOtherIncomeHelp.sumRedAmountBySheet(corpid, linkPreId);
        //剩余总的可红冲金额 = 关联原收入单总金额 - 原单总的已红冲金额(由于红冲金额为负数，因此此处用add)
        Double leftAmount = Arith.add(originAmout, redAmount);
        //其他收入单金额（此时还未处理成负数）
        Double sheetAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(dataList, OtherIncomeEnum.AMOUNT.getAttr(), 0D);
        if (sheetAmount > leftAmount) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_RED, OtherIncomeEnum.ORIGIN_ID.getAttrName());
        }
        //红冲金额置为负数，重新置入dataList内
        sheetAmount = Arith.mul(sheetAmount, -1);
        dataList.put(OtherIncomeEnum.AMOUNT.getAttr(), sheetAmount);
        otherIncomeSaveDTO.setDataList(dataList);

        //校验处理完毕后，再保存入库
        saveDb(sheetTypeEnum, otherIncomeSaveDTO, paasFormDataEntity, sheetAmount);
    }

    /**
     * 处理校验过数据后保存入库
     * @param sheetTypeEnum
     * @param otherIncomeSaveDTO
     * @param paasFormDataEntity
     * @param sheetAmount
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void saveDb(SheetTypeEnum sheetTypeEnum, OtherIncomeSaveDTO otherIncomeSaveDTO, PaasFormDataEntity paasFormDataEntity, Double sheetAmount) throws XbbException{
        JSONObject dataList = otherIncomeSaveDTO.getDataList();
        String corpid = otherIncomeSaveDTO.getCorpid();
        String userId = otherIncomeSaveDTO.getUserId();
        if (Objects.nonNull(otherIncomeSaveDTO.getProcessCreatorId())) {
            userId = otherIncomeSaveDTO.getProcessCreatorId();
        }
        OtherIncomeEntity otherIncomeEntity = new OtherIncomeEntity();
        BeanUtil.copyProperties(paasFormDataEntity, otherIncomeEntity);
        fundHelp.initSheetEntity4Save(userId, otherIncomeEntity);
        for (Map.Entry<String,Object> entry : SaasDataInitHelp.initPaymentSheet().entrySet()){
            SaasDataInitHelp.antDataSet(dataList,entry.getKey(),entry.getValue());
        }
        long now = DateUtil.getNow();
        otherIncomeEntity.setData(dataList);
        otherIncomeEntity.setAddTime(now);
        otherIncomeEntity.setUpdateTime(now);
        Long sheetId = null;
        try {
            otherIncomeModel.insert(otherIncomeEntity);
            sheetId = otherIncomeEntity.getId();
            //回滚ES 需要dataID
            paasFormDataEntity.setId(sheetId);

            Long accountId = FastJsonHelper.getLongOrDefaultFromFormData(dataList, OtherIncomeEnum.FUND_ACCOUNT.getAttr(), 0L);
            Long sheetTime = fundHelp.getSheetTime4FundFlow(dataList, OtherIncomeEnum.INCOME_TIME.getAttr(), otherIncomeSaveDTO.getExplainMap(), now);
            //账户余额变动（红冲类型的金额已经处理成负数）
            payAndPaymentSheetHelp.saveByPaymentSheetOrPaySheet(accountId, sheetAmount, corpid);
            //流水表日志记录
            FundAccountFlowEntity fundAccountFlowEntity = new FundAccountFlowEntity(corpid, now, otherIncomeEntity.getCreatorId(), FundAccountFlowTypeEnum.OTHER_INCOME.getCode(), sheetId, accountId, sheetTime, sheetAmount);
            fundAccountFlowModel.insert(fundAccountFlowEntity);
            //系统日志
            saasSaveHelp.sheetAddLog(otherIncomeSaveDTO, corpid, userId, otherIncomeEntity, XbbRefTypeEnum.OTHER_INCOME.getName(), OperateModuleTypeEnum.OTHER_FUND_MANAGEMENT);
        } catch (XbbException e) {
            //回滚流水(无流水的不需回滚)
            addRollBack4LinkEs(corpid, sheetId);
            LOG.error("保存其他收入单到数据库报错", e);
            throw e;
        } catch (Exception e) {
            //回滚流水(无流水的不需回滚)
            addRollBack4LinkEs(corpid, sheetId);
            LOG.error("保存其他收入单到数据库报错", e);
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208052, PaymentErrorCodeEnum.API_ERROR_208052.getMsg(), XbbRefTypeEnum.OTHER_INCOME.getName());
        }
    }
    /**
     * 新建失败回滚（主表和sub表通用接口已回滚，此处只回滚关联表）
     * @param corpid
     * @param sheetId
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void addRollBack4LinkEs(String corpid, Long sheetId) {
        //新建失败，回滚异步
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(() -> {
            try{
                //回滚流水es-直接删除es
                fundAccountFlowService.addRollback(corpid, FundAccountFlowTypeEnum.OTHER_INCOME.getCode(), Collections.singletonList(sheetId));
            } catch (XbbException e1) {
                LOG.error("otherIncome addRollBack4LinkEs rollback" + e1);
            }
        });
    }

    /**
     * 批量更新-只更新特定字段
     * @param otherIncomeUpdateBatchDTO
     * @return com.xbongbong.paas.toolbox.wrap.BaseVO
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private BaseVO updateAttrBatch(OtherIncomeUpdateBatchDTO otherIncomeUpdateBatchDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        try {
            String corpid = otherIncomeUpdateBatchDTO.getCorpid();
            List<OtherIncomeUpdateDTO> updateList = otherIncomeUpdateBatchDTO.getUpdateList();
            if (Objects.nonNull(updateList)  && !updateList.isEmpty()) {
                List<UpdateDataEntity> list = new ArrayList<>();
                updateList.forEach((item) -> {
                    list.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
                if (!list.isEmpty()) {
                    otherIncomeModel.updateBatch(list, corpid);
                }
            }
        } catch (Exception e) {
            LOG.error("OtherIncomeServiceImpl.updateBatch 批量更新出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return baseVO;
    }
}
